package com.xy.exam.service.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xy.exam.entity.User;
import com.xy.exam.mapper.UserMapper;
import com.xy.exam.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * @Author:徐莹
 * @Date:2025/04/14
 * 用户服务实现类
 * 使用Spring Security的PasswordEncoder进行密码加密
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Cacheable(value = "user", key = "'user_id_'+#id")
    @Override
    public User findUserById(Integer id) {
        return userMapper.selectById(id);
    }

    @Cacheable(value = "user", key = "'user_name_'+#username")
    @Override
    public User findUserByUsername(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        return userMapper.selectOne(queryWrapper);
    }

    @CachePut(value = "user", key = "'user_id_'+#result.id")
    @Override
    public User addUser(User user) {
        // 设置默认头像
        if (user.getAvatar() == null || user.getAvatar().isEmpty()) {
            user.setAvatar("/avatar/default.png");
        }
        
        // 盐值不再需要，BCrypt自动处理盐值
        user.setSalt(null);
        
        // 使用BCrypt加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        
        userMapper.insert(user);
        return user;
    }

    @CachePut(value = "user", key = "'user_id_'+#user.id")
    @Override
    public User updateUser(User user) {
        // 如果密码不为空，说明要修改密码
        if (user.getPassword() != null && !user.getPassword().isEmpty()) {
            // 使用BCrypt加密密码，不再需要盐值
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            user.setSalt(null);
        } else {
            // 不修改密码，从数据库获取原密码
            User oldUser = userMapper.selectById(user.getId());
            user.setPassword(oldUser.getPassword());
            // 盐值字段可以设为null
            user.setSalt(null);
        }
        
        userMapper.updateById(user);
        return user;
    }

    @CacheEvict(value = "user", key = "'user_id_'+#id")
    @Override
    public void deleteUser(Integer id) {
        userMapper.deleteById(id);
    }

    @Override
    public Page<User> findUserPage(Page<User> page) {
        return userMapper.selectPage(page, null);
    }

    @Override
    public User login(String username, String password) {
        // 根据用户名查询用户
        User user = findUserByUsername(username);
        if (user == null) {
            return null;
        }
        
        // 使用BCrypt验证密码
        if (passwordEncoder.matches(password, user.getPassword())) {
            return user;
        }
        
        return null;
    }

    @Override
    public User register(User user) {
        // 检查用户名是否已存在
        User existUser = findUserByUsername(user.getUsername());
        if (existUser != null) {
            return null;
        }
        
        // 添加用户
        return addUser(user);
    }

    @Override
    public boolean changePassword(Integer userId, String oldPassword, String newPassword) {
        // 根据ID查询用户
        User user = findUserById(userId);
        if (user == null) {
            return false;
        }
        
        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            return false;
        }
        
        // 更新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        // 盐值设为null，因为BCrypt自带盐值
        user.setSalt(null);
        userMapper.updateById(user);
        
        return true;
    }
} 